package fun.codedesign.principle.advice151.a014;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import fun.codedesign.principle.advice151.Good;

/**
 * 重写序列化方法 <br>
 * <pre>
 * </pre>
 *
 * @author zengjian
 * @create 2018-07-02 16:02
 * @since 1.0.0
 */
@Good("重写方法序列化需要的字段")
public class OverrideSerializableMethod {

    /**
     * 建议14：用序列化类的私有方法巧妙解决部分属性持久化问题
     * 例子：
     * 1. 计税系统只需要获得基础薪资和姓名，绩效薪资是隐藏的，如此就需要对绩效薪资进行隐蔽处理
     * <p>
     * 实际解决方案分类：
     * 方案1：避免传输过去绩效薪资， 但这样就丧失了相应的分布式能力
     * 方案2：增加一个类，只包含 属性：姓名和基本薪资
     * 方案3：请求端过滤，让计税系统过滤掉该数据，这和公开没区别，不可行
     * 方案4：变更传输契约，使用xml或者重建一个web service
     * 方案5：通过序列化私有方法对反序列化进行控制,控制读取绩效薪资为0，但丧失其分布式能力(见上)
     */
    class Person implements Serializable {
        private static final long serialVersionUID = 5292477129752662113L;
        private String name;
        private transient Salary salary;

        /**
         * 序列化化委托方法
         */
        private void writeObject(ObjectOutputStream out) throws IOException {
            out.defaultWriteObject();
            out.writeInt(salary.getBonus2());
        }

        /**
         * 反序列化时委托方法
         */
        private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException {
            in.defaultReadObject();
            salary = new Salary(in.readInt(), 0);
        }

        /**
         * 序列化时会利用反射检测序列化类中的方法是否有writeObject方法，有即调用，否则就按默认的
         * 反序列化的时候利用反射检测readObject方法，有即调用，否则按默认的序列化方法
         */
        public Salary getSalary() {
            return salary;
        }

        public void setSalary(Salary salary) {
            this.salary = salary;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

    }

    class Salary implements Serializable {
        private static final long serialVersionUID = -117199786787884198L;
        private int basePay;
        private int bonus;
        private transient int bonus2;

        public Salary(int basePay, int bonus) {
            this.basePay = basePay;
            this.bonus2 = bonus;
        }

        public int getBonus() {
            return bonus;
        }

        public int getBasePay() {
            return basePay;
        }

        public int getBonus2() {
            return bonus2;
        }
    }
}
